﻿ 
using System;
 
using System.Web.Mvc;
using System.Web.Security;
 


namespace CarTrackr.Controllers
{

    [HandleError]
    public class AccountController : Controller
    {

        private int  minRequiredPasswordLength = Membership.MinRequiredPasswordLength;

        public MembershipProvider Provider
        {
            get;
            private set;
        }

        public IFormsAuthentication FormsAuth
        {
            get;
            private set;
        }

        public AccountController()
            : this(null,null)
        {
        }

        public AccountController( IFormsAuthentication formsAuth, MembershipProvider provider)
        {
            FormsAuth = formsAuth ?? new FormsAuthenticationWrapper(); 
            Provider = provider ?? Membership.Provider;

            
        }

 
        public ActionResult Index()
        {
            return View();
        }

  
        public ActionResult Login()
		{
			return View();
		}


        [HttpPost]
		public ActionResult Login(string userName, string password,  bool? rememberMe)
		{

			if (!ValidateLogin(userName, password))
			{
				return View("Login");
			}

            FormsAuth.SetAuthCookie(userName, rememberMe ?? false);

		    return RedirectToAction("Index", "Home");
			 
		}

    

        public ActionResult Logout()
		{

			FormsAuth.SignOut();

			return RedirectToAction("Index", "Home");
		}

        public ActionResult Register()
		{

            ViewData["PasswordLength"] = minRequiredPasswordLength; 

			return View("Register");
		}


        [HttpPost] 
		public ActionResult Register(string userName, string email, string password, string confirmPassword)
		{

			ViewData["PasswordLength"] =  minRequiredPasswordLength; 

			if (!ValidateRegistration(userName, email, password, confirmPassword))
			{
                return View("Register");
			
			}

            MembershipCreateStatus createStatus = CreateUser(userName, password, email);

            if (createStatus == MembershipCreateStatus.Success)
            {
                FormsAuth.SetAuthCookie(userName, false);
                return RedirectToAction("Index", "Home");
            }

            ModelState.AddModelError("_FORM", MembershipCreateStatusToString(createStatus));

            return View("Register");
		}

   
        private  MembershipCreateStatus CreateUser(string userName, string password, string email)
		{
			MembershipCreateStatus status;
			Provider.CreateUser(userName, password, email, null, null, true, null, out status);
			return status;
		}

        private static string MembershipCreateStatusToString(MembershipCreateStatus createStatus)
		{
			switch (createStatus)
			{
				case MembershipCreateStatus.DuplicateUserName:
					return "Username already exists. Please enter a different user name.";

				case MembershipCreateStatus.DuplicateEmail:
					return "A username for that e-mail address already exists. Please enter a different e-mail address.";

				case MembershipCreateStatus.InvalidPassword:
					return "The password provided is invalid. Please enter a valid password value.";

				case MembershipCreateStatus.InvalidEmail:
					return "The e-mail address provided is invalid. Please check the value and try again.";

				case MembershipCreateStatus.InvalidAnswer:
					return "The password retrieval answer provided is invalid. Please check the value and try again.";

				case MembershipCreateStatus.InvalidQuestion:
					return "The password retrieval question provided is invalid. Please check the value and try again.";

				case MembershipCreateStatus.InvalidUserName:
					return "The user name provided is invalid. Please check the value and try again.";

				case MembershipCreateStatus.ProviderError:
					return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

				case MembershipCreateStatus.UserRejected:
					return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

				default:
					return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
			}
		}

        [Authorize]
		public ActionResult ChangePassword()
		{

            ViewData["PasswordLength"] = minRequiredPasswordLength; 

			return View();
		}


        [Authorize]
		[HttpPost]
		public ActionResult ChangePassword(string currentPassword, string newPassword, string confirmPassword)
		{

			ViewData["PasswordLength"] = minRequiredPasswordLength; 

			if (!ValidateChangePassword(currentPassword, newPassword, confirmPassword))
			{
			    return View();
	    	}
      
           if (Provider.ChangePassword(User.Identity.Name, currentPassword, newPassword))
	       {
					return RedirectToAction("ChangePasswordSuccess");
		   }
			 
		   ModelState.AddModelError("_FORM", "The current password is incorrect or the new password is invalid.");
		   
           return View();
		 
		}


  
        public ActionResult ChangePasswordSuccess()
		{

			return View();
        }


        #region Validation 

        private bool ValidateLogin(string userName, string password)
        {
            if (String.IsNullOrEmpty(userName))
            {
                ModelState.AddModelError("Username", "You must specify a username.");
            }
            if (String.IsNullOrEmpty(password))
            {
                ModelState.AddModelError("Password", "You must specify a password.");
            }

            if (!Provider.ValidateUser(userName, password))
            {
                MembershipUser membershipUser = Provider.GetUser(userName, false);

                if (membershipUser == null)
                {
                    ModelState.AddModelError("_FORM", "There is no user with the username " + userName);
                }
                else
                {
                    if (!membershipUser.IsApproved)
                    {
                        ModelState.AddModelError("_FORM", "Your account has not yet been approved.");
                    }
                    else if (membershipUser.IsLockedOut)
                    {

                        ModelState.AddModelError("_FORM", "Your account has been locked out.");
                    }
                    else
                    {
                        ModelState.AddModelError("_FORM", "Your password is incorrect.");
                    }
                }
            }
        

            return ModelState.IsValid;
        }



        private bool ValidateRegistration(string userName, string email, string password, string confirmPassword)
        {
            if (String.IsNullOrEmpty(userName))
            {
                ModelState.AddModelError("username", "You must specify a username.");
            }
            if (String.IsNullOrEmpty(email))
            {
                ModelState.AddModelError("email", "You must specify an email address.");
            }
            if (password == null || password.Length < minRequiredPasswordLength)
            {
                ModelState.AddModelError("password",
                    String.Format("You must specify a password of {0} or more characters.",
                                   minRequiredPasswordLength));
            }
            if (!String.Equals(password, confirmPassword, StringComparison.Ordinal))
            {
                ModelState.AddModelError("_FORM", "The new password and confirmation password do not match.");
            }
            return ModelState.IsValid;
        }


        private bool ValidateChangePassword(string currentPassword, string newPassword, string confirmPassword)
        {
            if (String.IsNullOrEmpty(currentPassword))
            {
                ModelState.AddModelError("currentPassword", "You must specify a current password.");
            }
            if (newPassword == null || newPassword.Length < minRequiredPasswordLength)
            {
                ModelState.AddModelError("newPassword",
                    String.Format("You must specify a new password of {0} or more characters.",
                           minRequiredPasswordLength));
            }

            if (!String.Equals(newPassword, confirmPassword, StringComparison.Ordinal))
            {
                ModelState.AddModelError("_FORM", "The new password and confirmation password do not match.");
            }

            return ModelState.IsValid;
        }

        #endregion
    }


    public interface IFormsAuthentication
    {
        void SetAuthCookie(string userName, bool createPersistentCookie);
        void SignOut();
    }

    public class FormsAuthenticationWrapper : IFormsAuthentication
    {
        public void SetAuthCookie(string userName, bool createPersistentCookie)
        {
            FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
        }
        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }
    }
}

